﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Internal;
using FDEEPublicFunc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FDEEInterface
{
    public static class BlockTool
    {
        #region 块插入

        /// <summary>
        /// 复制指定数据库中的指定块
        /// </summary>
        public static void CopyBlockFromFile(this Database TargetDB, string FileName, string BlockName, DuplicateRecordCloning Method = DuplicateRecordCloning.Replace)
        {
            using (Database db = new Database(false, true))
            {
                db.ReadDwgFile(FileName, FileShare.Read, true, "");

                ObjectIdCollection ids = new ObjectIdCollection();
                ObjectIdCollection newoids = new ObjectIdCollection();
                IdMapping im = new IdMapping();

                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                    ids.Add(bt[BlockName]);
                    //BlockTable blockTbl = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable; //以写方式打开块表
                    //BlockTableRecord modelSpace = tr.GetObject(bt[BlockTableRecord.ModelSpace],//以写的方式打开模型空间块表记录
                    //    OpenMode.ForWrite) as BlockTableRecord;

                    tr.Commit();
                }

                db.WblockCloneObjects(ids, TargetDB.BlockTableId, im, DuplicateRecordCloning.Replace, false);
            }
        }

        public static void InitialZwBlockReference(string path, string BlockName)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
            string fileName = path;
            ObjectIdCollection oids = new ObjectIdCollection();
            ObjectIdCollection newoids = new ObjectIdCollection();
            IdMapping idMap = new IdMapping();
            //将动态块拷贝到当前document，生成块定义
            using (Database srcDb = new Database(false, false))
            {
                srcDb.ReadDwgFile(fileName, System.IO.FileShare.ReadWrite, true, null);
                srcDb.CloseInput(true);
                using (Transaction tr = srcDb.TransactionManager.StartTransaction())
                {
                    BlockTable blockTbl = tr.GetObject(srcDb.BlockTableId, OpenMode.ForRead) as BlockTable;
                    BlockTableRecord modelSpace1 = tr.GetObject(blockTbl[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
                    foreach (ObjectId oid in modelSpace1)
                    {
                        oids.Add(oid);
                    }
                }
                srcDb.WblockCloneObjects(oids, db.CurrentSpaceId, idMap, DuplicateRecordCloning.Replace, false);
                foreach (ObjectId oid in oids)
                {
                    try
                    {
                        if (!newoids.Contains(idMap[oid].Value))
                        {
                            newoids.Add(idMap[oid].Value);
                        }
                    }
                    catch { }

                }
            }
            //设置显示的值
            using (DocumentLock dl = doc.LockDocument())
            {
                using (Transaction trans = doc.TransactionManager.StartTransaction())
                {
                    Entity ent = trans.GetObject(newoids[0], OpenMode.ForWrite) as Entity;
                    if (ent is BlockReference)
                    {
                        CheckBlockPropertyValue((BlockReference)ent, BlockName);
                    }
                    trans.Commit();
                }
            }
        }


        //根据想要显示的值去显示
        public static void CheckBlockPropertyValue(BlockReference br, string blockName)
        {
            DynamicBlockReferencePropertyCollection properties = br.DynamicBlockReferencePropertyCollection;
            for (int i = 0; i < properties.Count; i++)
            {
                DynamicBlockReferenceProperty property = properties[i];
                foreach (object item in property.GetAllowedValues())
                {
                    if (item.ToString() == blockName)
                    {
                        property.Value = item;
                    }
                }
            }
        }



        /// <summary>
        /// 插入模型空间
        /// </summary>
        /// <param name="insertPoint"></param>
        /// <param name="scale"></param>
        /// <param name="blockName"></param>
        /// <param name="filePash"></param>
        /// <returns></returns>
        public static BlockReference InsertBlockReference(Point3d insertPoint, double scale, string blockName, string filePash,double ang=0,bool isModel=true)
        {
            BlockReference blockReference = null;

            Document curDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; //获取当前文档
            //Document curDoc = doc; //获取当前文档
            using (DocumentLock docLock = curDoc.LockDocument()) //锁定文档
            {
                using (Transaction trans = curDoc.TransactionManager.StartTransaction()) //事务
                {
                    try
                    {
                        BlockTable curBlockTb = trans.GetObject(curDoc.Database.BlockTableId, OpenMode.ForRead) as BlockTable; //当前文档块表
                        ObjectId blockObjId = new ObjectId(); //用于块表记录的编号
                        if (curBlockTb.Has(blockName) && !curBlockTb[blockName].IsErased) //块表中存在该块表记录, 并且没有被删除
                            blockObjId = curBlockTb[blockName];
                        else
                        {
                            if (!System.IO.File.Exists(filePash)) //不存在该文件
                            {
                                trans.Abort(); //事务终止
                                return blockReference;
                            }
                            Database sourceDB = new Database(false, true);
                            sourceDB.ReadDwgFile(filePash, FileShare.Read, true, null); //后台读取DWG文件信息; 参数: 文件名, 打开方式, 是否允许转换版本, 密码
                            blockObjId = curDoc.Database.Insert(blockName, sourceDB, false); //将一个数据库插入到当前数据库的一个块中; 参数: 新创建的块表记录名, 资源数据库, 资源数据库是否保存原样
                            sourceDB.CloseInput(true); //是否关闭ReadDwgFile()方法之后打开的文件
                            sourceDB.Dispose();
                        }
                        if (blockObjId != null)
                        {
                            string layoutName = LayoutManager.Current.CurrentLayout; //获得当前布局空间
                            BlockTableRecord block = trans.GetObject(blockObjId, OpenMode.ForWrite) as BlockTableRecord; //根据块表记录编号获取的块表记录, 用于取得它的属性定义
                            block.Explodable = true; //块参照是否能被炸开
                            blockReference = new BlockReference(insertPoint, blockObjId); //新建块参照
                            BlockTableRecord layout = null;
                            if (isModel)
                                layout = trans.GetObject(curBlockTb[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; //根据当前布局空间获取的表块记录, 用于将块插入布局空间中
                            else
                                layout = trans.GetObject(curBlockTb[BlockTableRecord.PaperSpace], OpenMode.ForWrite) as BlockTableRecord;
                            layout.AppendEntity(blockReference); //在当前空间中追加此块参照
                            trans.AddNewlyCreatedDBObject(blockReference, true);
                        }
                        blockReference.TransformBy(Matrix3d.Scaling(scale, insertPoint)); //缩放块; 修改块比例
                        blockReference.Rotation = ang;
                        trans.Commit(); //提交事务
                    }
                    catch (System.Exception ex)
                    {
                        if (blockReference != null)
                        {
                            blockReference = null;
                        }
                        return blockReference;
                    }
                }
            }

            return blockReference;
        }

        public static BlockReference InsertBlockReference(Point3d insertPoint, double scale, string blockName, string filePash,ref Extents2d ext, double ang = 0)
        {
            BlockReference blockReference = null;

            Document curDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; //获取当前文档
            //Document curDoc = doc; //获取当前文档
            using (DocumentLock docLock = curDoc.LockDocument()) //锁定文档
            {
                using (Transaction trans = curDoc.TransactionManager.StartTransaction()) //事务
                {
                    try
                    {
                        BlockTable curBlockTb = trans.GetObject(curDoc.Database.BlockTableId, OpenMode.ForRead) as BlockTable; //当前文档块表
                        ObjectId blockObjId = new ObjectId(); //用于块表记录的编号
                        if (curBlockTb.Has(blockName) && !curBlockTb[blockName].IsErased) //块表中存在该块表记录, 并且没有被删除
                            blockObjId = curBlockTb[blockName];
                        else
                        {
                            if (!System.IO.File.Exists(filePash)) //不存在该文件
                            {
                                trans.Abort(); //事务终止
                                return blockReference;
                            }
                            Database sourceDB = new Database(false, true);
                            sourceDB.ReadDwgFile(filePash, FileShare.Read, true, null); //后台读取DWG文件信息; 参数: 文件名, 打开方式, 是否允许转换版本, 密码
                            blockObjId = curDoc.Database.Insert(blockName, sourceDB, false); //将一个数据库插入到当前数据库的一个块中; 参数: 新创建的块表记录名, 资源数据库, 资源数据库是否保存原样
                            sourceDB.CloseInput(true); //是否关闭ReadDwgFile()方法之后打开的文件
                            sourceDB.Dispose();
                        }
                        if (blockObjId != null)
                        {
                            string layoutName = LayoutManager.Current.CurrentLayout; //获得当前布局空间
                            BlockTableRecord block = trans.GetObject(blockObjId, OpenMode.ForWrite) as BlockTableRecord; //根据块表记录编号获取的块表记录, 用于取得它的属性定义
                            block.Explodable = true; //块参照是否能被炸开
                            blockReference = new BlockReference(insertPoint, blockObjId); //新建块参照
                            BlockTableRecord layout = null;
                            if (layoutName.Equals("Model"))
                                layout = trans.GetObject(curBlockTb[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; //根据当前布局空间获取的表块记录, 用于将块插入布局空间中
                            else
                                layout = trans.GetObject(curBlockTb[BlockTableRecord.PaperSpace], OpenMode.ForWrite) as BlockTableRecord;
                            layout.AppendEntity(blockReference); //在当前空间中追加此块参照
                            trans.AddNewlyCreatedDBObject(blockReference, true);
                        }
                        blockReference.TransformBy(Matrix3d.Scaling(scale, insertPoint)); //缩放块; 修改块比例
                        blockReference.Rotation = ang;
                      
                        trans.Commit(); //提交事务
                        ext = ext.Add(new Extents2d(blockReference.Bounds.Value.MinPoint.Convert2D(), blockReference.Bounds.Value.MaxPoint.Convert2D()));
                    }
                    catch (System.Exception ex)
                    {
                        if (blockReference != null)
                        {
                            blockReference = null;
                        }
                        return blockReference;
                    }
                }
            }

            return blockReference;
        }
        /// <summary>
        /// 插入布局
        /// </summary>
        /// <param name="insertPoint"></param>
        /// <param name="scale"></param>
        /// <param name="blockName"></param>
        /// <param name="filePash"></param>
        /// <returns></returns>
        public static BlockReference InsertBlockReferencePaperSpace(Point3d insertPoint, double scale, string blockName, string filePash, double ang = 0)
        {
            BlockReference blockReference = null;

            Document curDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; //获取当前文档
            //Document curDoc = doc; //获取当前文档
            using (DocumentLock docLock = curDoc.LockDocument()) //锁定文档
            {
                using (Transaction trans = curDoc.TransactionManager.StartTransaction()) //事务
                {
                    try
                    {
                        BlockTable curBlockTb = trans.GetObject(curDoc.Database.BlockTableId, OpenMode.ForRead) as BlockTable; //当前文档块表
                        ObjectId blockObjId = new ObjectId(); //用于块表记录的编号
                        if (curBlockTb.Has(blockName) && !curBlockTb[blockName].IsErased) //块表中存在该块表记录, 并且没有被删除
                            blockObjId = curBlockTb[blockName];
                        else
                        {
                            if (!System.IO.File.Exists(filePash)) //不存在该文件
                            {
                                trans.Abort(); //事务终止
                                return blockReference;
                            }
                            Database sourceDB = new Database(false, true);
                            sourceDB.ReadDwgFile(filePash, FileShare.Read, true, null); //后台读取DWG文件信息; 参数: 文件名, 打开方式, 是否允许转换版本, 密码
                            blockObjId = curDoc.Database.Insert(blockName, sourceDB, false); //将一个数据库插入到当前数据库的一个块中; 参数: 新创建的块表记录名, 资源数据库, 资源数据库是否保存原样
                            sourceDB.CloseInput(true); //是否关闭ReadDwgFile()方法之后打开的文件
                            sourceDB.Dispose();
                        }
                        if (blockObjId != null)
                        {
                            string layoutName = LayoutManager.Current.CurrentLayout; //获得当前布局空间
                            BlockTableRecord block = trans.GetObject(blockObjId, OpenMode.ForWrite) as BlockTableRecord; //根据块表记录编号获取的块表记录, 用于取得它的属性定义
                            block.Explodable = true; //块参照是否能被炸开
                            blockReference = new BlockReference(insertPoint, blockObjId); //新建块参照
                            BlockTableRecord layout = null;
                            //if (layoutName.Equals("Model"))
                            //    layout = trans.GetObject(curBlockTb[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; //根据当前布局空间获取的表块记录, 用于将块插入布局空间中
                            //else
                            layout = trans.GetObject(curBlockTb[BlockTableRecord.PaperSpace], OpenMode.ForWrite) as BlockTableRecord;
                            layout.AppendEntity(blockReference); //在当前空间中追加此块参照
                            trans.AddNewlyCreatedDBObject(blockReference, true);
                        }
                        blockReference.TransformBy(Matrix3d.Scaling(scale, insertPoint)); //缩放块; 修改块比例
                        blockReference.Rotation = ang;
                        trans.Commit(); //提交事务
                    }
                    catch (System.Exception ex)
                    {
                        if (blockReference != null)
                        {
                            blockReference = null;
                        }
                        return blockReference;
                    }
                }
            }

            return blockReference;
        }

        #endregion

        #region 其他快插入方法

        /// <summary>
        /// 插入带属性的参照快(插入动态块)
        /// </summary>
        /// <param name="spaceId">空间的ID</param>
        /// <param name="layer">块要加入的图层名</param>
        /// <param name="blockName">快参照所属的快名</param>
        /// <param name="postion">插入点</param>
        /// <param name="scale">缩放比例</param>
        /// <param name="rotateAngle">旋转角度</param>
        /// <param name="attNameValues">属性名称与取值</param>
        /// <returns></returns>
        public static ObjectId InsertBlockrefence(this ObjectId spaceId, string layer, string blockName, Point3d postion, Scale3d scale, double rotateAngle, Dictionary<string, string> attNameValues)
        {
            // 获取数据库对象
            Database db = spaceId.Database;
            //以读的方式打开块表
            BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
            //如果没有blockName d的块，则程序返回
            if (!bt.Has(blockName))

                return ObjectId.Null;//如果没有blockName的块，程序返回
            //以写的模式打开空间
            BlockTableRecord space = (BlockTableRecord)spaceId.GetObject(OpenMode.ForWrite);
            //获取块表的记录ID
            ObjectId btrId = bt[blockName];
            //打开块表记录
            BlockTableRecord record = btrId.GetObject(OpenMode.ForRead) as BlockTableRecord;
            //创建一个快参照并设置插入点
            BlockReference br = new BlockReference(postion, bt[blockName]);

            br.ScaleFactors = scale;

            br.Layer = layer;
            br.Rotation = rotateAngle;

            space.AppendEntity(br);
            //判断块表记录是否包含属性定义
            if (record.HasAttributeDefinitions)
            {
                //若包含，则遍历属性定义
                foreach (ObjectId id in record)
                {
                    //检查是否是属性定义
                    AttributeDefinition attDef = id.GetObject(OpenMode.ForRead) as AttributeDefinition;

                    if (attDef != null)
                    {

                        //创建一个新的属性对象
                        AttributeReference attribute = new AttributeReference();
                        //从属性定义获取属性对象的对象特性
                        attribute.SetAttributeFromBlock(attDef, br.BlockTransform);
                        attribute.Rotation = attDef.Rotation;

                        attribute.Position = attDef.Position.TransformBy(br.BlockTransform);

                        attribute.AdjustAlignment(db);
                        //判断是否包含指定的属性名称
                        if (attNameValues.ContainsKey(attDef.Tag.ToUpper()))
                        {

                            //设置属性值
                            attribute.TextString = attNameValues[attDef.Tag.ToUpper()].ToString();

                        }
                        // 向块参照添加属性对象
                        br.AttributeCollection.AppendAttribute(attribute);
                        db.TransactionManager.AddNewlyCreatedDBObject(attribute, true);

                    }
                }
            }
            db.TransactionManager.AddNewlyCreatedDBObject(br, true);
            return br.ObjectId;//返回添加的快参照的ID
        }
        /// <summary>
        /// 插入带属性的参照快(插入动态块)
        /// </summary>
        /// <param name="spaceId">空间的ID</param>
        /// <param name="layer">块要加入的图层名</param>
        /// <param name="blockName">快参照所属的快名</param>
        /// <param name="postion">插入点</param>
        /// <param name="scale">缩放比例</param>
        /// <param name="rotateAngle">旋转角度</param>
        /// <param name="attNameValues">属性名称与取值</param>
        /// <returns></returns>
        public static ObjectId InsertBlockrefenceModelSpace(this ObjectId spaceId, string blockName, Point3d postion, Scale3d scale, double rotateAngle, Dictionary<string, string> attNameValues)
        {
            // 获取数据库对象
            Database db = spaceId.Database;
            //以读的方式打开块表
            BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
            //如果没有blockName d的块，则程序返回
            if (!bt.Has(blockName))

                return ObjectId.Null;//如果没有blockName的块，程序返回
            //以写的模式打开空间
            BlockTableRecord space = (BlockTableRecord)spaceId.GetObject(OpenMode.ForWrite);
            //获取块表的记录ID
            ObjectId btrId = bt[blockName];
            //打开块表记录
            BlockTableRecord record = btrId.GetObject(OpenMode.ForRead) as BlockTableRecord;
            //创建一个快参照并设置插入点
            BlockReference br = new BlockReference(postion, bt[blockName]);

            br.ScaleFactors = scale;

            br.Rotation = rotateAngle;

            space.AppendEntity(br);
            //判断块表记录是否包含属性定义
            if (record.HasAttributeDefinitions)
            {
                //若包含，则遍历属性定义
                foreach (ObjectId id in record)
                {
                    //检查是否是属性定义
                    AttributeDefinition attDef = id.GetObject(OpenMode.ForRead) as AttributeDefinition;

                    if (attDef != null)
                    {

                        //创建一个新的属性对象
                        AttributeReference attribute = new AttributeReference();
                        //从属性定义获取属性对象的对象特性
                        attribute.SetAttributeFromBlock(attDef, br.BlockTransform);
                        attribute.Rotation = attDef.Rotation;

                        attribute.Position = attDef.Position.TransformBy(br.BlockTransform);

                        attribute.AdjustAlignment(db);
                        //判断是否包含指定的属性名称
                        if (attNameValues.ContainsKey(attDef.Tag.ToUpper()))
                        {

                            //设置属性值
                            attribute.TextString = attNameValues[attDef.Tag.ToUpper()].ToString();

                        }
                        // 向块参照添加属性对象
                        br.AttributeCollection.AppendAttribute(attribute);
                        db.TransactionManager.AddNewlyCreatedDBObject(attribute, true);

                    }
                }
            }
            db.TransactionManager.AddNewlyCreatedDBObject(br, true);
            return br.ObjectId;//返回添加的快参照的ID
        }
        public static ObjectId InsertBlockrefenceModelSpace(this ObjectId spaceId, string blockName, Point3d postion, Scale3d scale, double rotateAngle, Dictionary<string, string> attNameValues,ref Extents2d ext)
        {
            // 获取数据库对象
            Database db = spaceId.Database;
            //以读的方式打开块表
            BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
            //如果没有blockName d的块，则程序返回
            if (!bt.Has(blockName))

                return ObjectId.Null;//如果没有blockName的块，程序返回
            //以写的模式打开空间
            BlockTableRecord space = (BlockTableRecord)spaceId.GetObject(OpenMode.ForWrite);
            //获取块表的记录ID
            ObjectId btrId = bt[blockName];
            //打开块表记录
            BlockTableRecord record = btrId.GetObject(OpenMode.ForRead) as BlockTableRecord;
            //创建一个快参照并设置插入点
            BlockReference br = new BlockReference(postion, bt[blockName]);

            br.ScaleFactors = scale;

            br.Rotation = rotateAngle;

            space.AppendEntity(br);
            //判断块表记录是否包含属性定义
            if (record.HasAttributeDefinitions)
            {
                //若包含，则遍历属性定义
                foreach (ObjectId id in record)
                {
                    //检查是否是属性定义
                    AttributeDefinition attDef = id.GetObject(OpenMode.ForRead) as AttributeDefinition;

                    if (attDef != null)
                    {

                        //创建一个新的属性对象
                        AttributeReference attribute = new AttributeReference();
                        //从属性定义获取属性对象的对象特性
                        attribute.SetAttributeFromBlock(attDef, br.BlockTransform);
                        attribute.Rotation = attDef.Rotation;

                        attribute.Position = attDef.Position.TransformBy(br.BlockTransform);

                        attribute.AdjustAlignment(db);
                        //判断是否包含指定的属性名称
                        if (attNameValues.ContainsKey(attDef.Tag.ToUpper()))
                        {

                            //设置属性值
                            attribute.TextString = attNameValues[attDef.Tag.ToUpper()].ToString();

                        }
                        // 向块参照添加属性对象
                        br.AttributeCollection.AppendAttribute(attribute);
                        db.TransactionManager.AddNewlyCreatedDBObject(attribute, true);

                    }
                }
            }
            db.TransactionManager.AddNewlyCreatedDBObject(br, true);
            ext = ext.Add(new Extents2d(br.Bounds.Value.MinPoint.Convert2D(), br.Bounds.Value.MaxPoint.Convert2D()));
            return br.ObjectId;//返回添加的快参照的ID
        }
        public static BlockReference InsertBlockReference(Point3d insertPoint, double scale, string blockName, string filePash, Dictionary<string, Dictionary<string, string>> attNameValues, Dictionary<string, Dictionary<string, string>> attDNameValues, ref Extents2d ext, double angle = 0, bool isMirror = false)
        {
            BlockReference blockReference = null;

            Document curDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; //获取当前文档
            using (DocumentLock docLock = curDoc.LockDocument()) //锁定文档
            {
                using (Transaction trans = curDoc.TransactionManager.StartTransaction()) //事务
                {
                    try
                    {
                        BlockTable curBlockTb = trans.GetObject(curDoc.Database.BlockTableId, OpenMode.ForRead) as BlockTable; //当前文档块表
                        ObjectId blockObjId = new ObjectId(); //用于块表记录的编号
                        if (curBlockTb.Has(blockName) && !curBlockTb[blockName].IsErased) //块表中存在该块表记录, 并且没有被删除
                            blockObjId = curBlockTb[blockName];
                        else
                        {
                            if (!System.IO.File.Exists(filePash)) //不存在该文件
                            {
                                trans.Abort(); //事务终止
                                return blockReference;
                            }
                            Database sourceDB = new Database(false, true);
                            sourceDB.ReadDwgFile(filePash, FileShare.Read, true, null); //后台读取DWG文件信息; 参数: 文件名, 打开方式, 是否允许转换版本, 密码
                            blockObjId = curDoc.Database.Insert(blockName, sourceDB, false); //将一个数据库插入到当前数据库的一个块中; 参数: 新创建的块表记录名, 资源数据库, 资源数据库是否保存原样
                            sourceDB.CloseInput(true); //是否关闭ReadDwgFile()方法之后打开的文件
                            sourceDB.Dispose();
                        }
                        if (blockObjId != null)
                        {
                            string layoutName = LayoutManager.Current.CurrentLayout; //获得当前布局空间
                            BlockTableRecord block = trans.GetObject(blockObjId, OpenMode.ForWrite) as BlockTableRecord; //根据块表记录编号获取的块表记录, 用于取得它的属性定义
                            block.Explodable = true; //块参照是否能被炸开
                            blockReference = new BlockReference(insertPoint, blockObjId); //新建块参照
                            BlockTableRecord layout = null;
                            if (layoutName.Equals("Model"))
                                layout = trans.GetObject(curBlockTb[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; //根据当前布局空间获取的表块记录, 用于将块插入布局空间中
                            else
                                layout = trans.GetObject(curBlockTb[BlockTableRecord.PaperSpace], OpenMode.ForWrite) as BlockTableRecord;
                            layout.AppendEntity(blockReference); //在当前空间中追加此块参照
                            trans.AddNewlyCreatedDBObject(blockReference, true);
                            //if (isMirror)
                            //    blockReference.Mirror(insertPoint, insertPoint.Convert3D(0, -100), true);
                            if (!block.HasAttributeDefinitions) //如果该块表记录中不包含任何属性定义
                                goto No_AttributeDefinitions; //直接去往No_AttributeDefinitions

                            AttributeDefinition attriDef = null;
                            AttributeReference attriRefe = null;
                            Matrix3d mtr = Matrix3d.Displacement(block.Origin.GetVectorTo(insertPoint)); //Displacement 取代
                            foreach (ObjectId entityObjId in block) //遍历块表记录中的实体编号
                            {
                                attriDef = trans.GetObject(entityObjId, OpenMode.ForRead) as AttributeDefinition; //打开实体通过实体编号
                                if (attriDef == null) //若还是为null
                                    continue;
                                attriRefe = new AttributeReference(); //每次循环new一次新的对象, 确保上次属性不会残留
                                attriRefe.SetPropertiesFrom(attriDef); //SetPropertiesFrom 设置属性来自
                                attriRefe.SetAttributeFromBlock(attriDef, mtr); //通过块设置属性 参数: 属性定义, 变形矩阵
                                attriRefe.TextString = ""; //设置属性值为""
                                                           //if (attDNameValues.Keys.Contains(prop.PropertyName) && !prop.ReadOnly)
                                if (attNameValues != null)
                                {
                                    if (attNameValues.Keys.Contains(attriRefe.Tag))
                                    {
                                        Dictionary<string, string> dic = attNameValues[attriRefe.Tag];
                                        List<string> values = dic.Keys.ToList();
                                        //设置属性值
                                        attriRefe.TextString = values[0];

                                    }
                                }
                                blockReference.AttributeCollection.AppendAttribute(attriRefe); //块参照中添加此属性参照
                                trans.AddNewlyCreatedDBObject(attriRefe, true);
                                attriRefe = null;
                            }
                            //UpdateAttributesInBlock(blockObjId, para);
                        }
                        No_AttributeDefinitions:
                        if (attDNameValues != null)
                        {
                            ChangeDynamicValue(blockReference, attDNameValues);
                        }
                        //blockReference.Layer = "HA";
                        blockReference.TransformBy(Matrix3d.Scaling(scale, insertPoint)); //缩放块; 修改块比例
                                                                                          //blockReference.Rotate(insertPoint, GeTools.DegreeToRadian(angle));
                        ext = ext.Add(new Extents2d(blockReference.Bounds.Value.MinPoint.Convert2D(), blockReference.Bounds.Value.MaxPoint.Convert2D()));
                        trans.Commit(); //提交事务
                    }
                    catch (System.Exception ex)
                    {
                        if (blockReference != null)
                        {
                            blockReference = null;
                        }
                        return blockReference;
                    }
                }
            }

            return blockReference;
        }

        public static void ChangeDynamicValue(BlockReference br, Dictionary<string, Dictionary<string, string>> attDNameValues)
        {
            if (br != null && br.IsDynamicBlock)
            {
                DynamicBlockReferencePropertyCollection pc = br.DynamicBlockReferencePropertyCollection;
                AttributeCollection ar = br.AttributeCollection;

                foreach (DynamicBlockReferenceProperty prop in pc)
                {
                    if (attDNameValues.Keys.Contains(prop.PropertyName) && !prop.ReadOnly)
                    {
                        try
                        {
                            Dictionary<string, string> dic = attDNameValues[prop.PropertyName];
                            List<string> values = dic.Keys.ToList();
                            List<string> types = dic.Values.ToList();
                            switch (types[0].ToLower())
                            {
                                case "double":
                                    string[] sp = prop.PropertyName.Split('_');
                                    if (sp != null)
                                    {
                                        //if(sp[sp.Length-1]=="mm")
                                        //    prop.Value = double.Parse(values[0])/1000;
                                        //else
                                        prop.Value = double.Parse(values[0]);
                                    }
                                    break;
                                case "string":
                                    prop.Value = values[0];
                                    break;
                                case "int":                                   
                                        prop.Value = int.Parse(values[0]);
                                    break;
                            }
                            //prop.Value = attDNameValues[prop.PropertyName];

                        }
                        catch (System.Exception ex)
                        {

                        }
                    }
                    else
                    {
                        continue;
                    }

                }
            }

        }
        /// <summary>
        /// 获取动态块的动态属性值
        /// </summary>
        /// <param name="blockId"></param>
        /// <param name="propName"></param>
        /// <returns></returns>
        public static string GetDynBlockValue(this ObjectId blockId, string propName)
        {
            string propValue = null;//用于返回动态属性值的变量

            var props = blockId.GetDynProperties();//获得动态块的所有属性

            //遍历动态属性
            foreach (DynamicBlockReferenceProperty prop in props)
            {
                //如果动态属性的名称与输入的名称相同
                if (prop.PropertyName == propName)
                {
                    //获取动态属性值并结束遍历
                    propValue = prop.Value.ToString();

                    break;
                }

            }

            return propValue;
        }

        /// <summary>
        /// 获得动态块的所有属性
        /// </summary>
        /// <returns></returns>
        public static DynamicBlockReferencePropertyCollection GetDynProperties(this ObjectId blockId)
        {
            BlockReference br = blockId.GetObject(OpenMode.ForRead) as BlockReference;

            if (br == null && !br.IsDynamicBlock) return null;

            return br.DynamicBlockReferencePropertyCollection;  //返回动态块的动态属性

        }

        /// <summary>
        /// 设置动态属性值(遍历动态块中的属性，对符合条件的进行赋值；)
        /// </summary>
        /// <param name="blockId"></param>
        /// <param name="PropName"></param>
        /// <param name="value"></param>
        public static void SetDynBlockValue(this ObjectId blockId, string PropName, object value)
        {
            var props = blockId.GetDynProperties();//获取动态块的所有属性

            foreach (DynamicBlockReferenceProperty prop in props)
            {
                //如果动态属性的名称与输入的名称相同且为可读
                if (prop.ReadOnly == false && prop.PropertyName == PropName)
                {
                    prop.Value = value;
                    }
                ////如果动态属性的名称与输入的名称相同且为可读
                //if (prop.ReadOnly == false && prop.PropertyName == PropName)
                //{
                //    //判断动态属性的类型并通过转换类型设置正确的动态属性值
                //    switch (prop.PropertyTypeCode)
                //    {
                //        case (short)DynBlockPropTypeCode.Short:
                //            prop.Value = Convert.ToInt16(value);
                //            break;
                //        case (short)DynBlockPropTypeCode.Long:
                //            prop.Value = Convert.ToInt64(value);
                //            break;
                //        case (short)DynBlockPropTypeCode.Real:
                //            prop.Value = Convert.ToDouble(value);
                //            break;

                //        default:
                //            prop.Value = value;
                //            break;


                //    }
                //    break;
                //}
            }
        }

        /// <summary>
        /// 为实体添加指定的注释比例
        /// </summary>
        /// <param name="entId">实体的ObjectId</param>
        /// <param name="scaleNames">注释比例名列表</param>
        public static void AttachScale(this ObjectId entId, params string[] scaleNames)
        {
            Database db = entId.Database;

            DBObject obj = entId.GetObject(OpenMode.ForRead);//获取entID的实体对象

            if (obj.Annotative != AnnotativeStates.NotApplicable)//如果实体支持注释缩 放
            {
                if (obj is BlockReference)
                {
                    BlockReference br = obj as BlockReference;
                    //打开对应的块表记录
                    BlockTableRecord btr = (BlockTableRecord)br.BlockTableRecord.GetObject(OpenMode.ForWrite);
                    //设置块表记录为可注释缩放
                    btr.Annotative = AnnotativeStates.True;
                }
                else if (obj.Annotative == AnnotativeStates.False)
                    obj.Annotative = AnnotativeStates.True;

                obj.UpgradeOpen();//切换实体为写的状态以添加注释比例
                //获取当前图形的对象比例管理器
                ObjectContextManager ocm = db.ObjectContextManager;

                //获得当前的图形的注释比例列表，
                ObjectContextCollection occ = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");
                foreach (string scaleName in scaleNames)
                {
                    //获取名为scaleName的注释比例
                    ObjectContext scale = occ.GetContext(scaleName);
                    //若不存在scaleName的注释比例，则结束本次循环
                    if (scale == null) continue;
                    //为实体添加名为scaleName的注释比例

                    ObjectContexts.AddContext(obj, scale);// ObjectContexts要添加acmgdinternal.dll引用
                }
                obj.DowngradeOpen();//为了安全将实体切换为读的状态
            }

        }

        #endregion
    }
}
